package com.intelligentpension.kotlinbluetooth.ble

import android.Manifest
import android.annotation.SuppressLint
import android.bluetooth.*
import android.bluetooth.le.AdvertiseCallback
import android.bluetooth.le.AdvertiseData
import android.bluetooth.le.AdvertiseSettings
import android.bluetooth.le.BluetoothLeAdvertiser
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.os.ParcelUuid
import android.os.SystemClock
import android.util.Log
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import com.hjq.toast.ToastUtils
import com.intelligentpension.kotlinbluetooth.R
import com.intelligentpension.kotlinbluetooth.utils.Contect
import com.intelligentpension.kotlinbluetooth.utils.ThreadUtils
import com.orhanobut.logger.Logger
import java.util.*


class LowPowerServerActivity : AppCompatActivity() {
    private lateinit var mTips: TextView
    private lateinit var mBluetoothLeAdvertiser: BluetoothLeAdvertiser//BLE广播
    private lateinit var mBluetoothGattServer: BluetoothGattServer //BLE服务端

    //BLE服务端Callback
    private var mBluetoothGattServerCallback = object :BluetoothGattServerCallback(){

        @SuppressLint("MissingPermission")
        override fun onConnectionStateChange(device: BluetoothDevice?, status: Int, newState: Int) {
            super.onConnectionStateChange(device, status, newState)
            Logger.e(String.format("onConnectionStateChange:%s,%s,%s,%s",device?.name,device?.address,status,newState))
            logTV(String.format(if (status==0) if (newState ==2) "与[%s]连接成功" else "与[%s]连接断开" else ("与[%s]连接出错,错误码:$status"),device) )
        }

        override fun onServiceAdded(status: Int, service: BluetoothGattService?) {
            super.onServiceAdded(status, service)
            Logger.e("onServiceAdded:%s,%s",status,service?.uuid)
            logTV(String.format( if (status==0) "添加服务[%s]成功" else "添加服务[%s]失败,错误码:$status",service?.uuid))
        }

        @SuppressLint("MissingPermission")
        override fun onCharacteristicReadRequest(device: BluetoothDevice?, requestId: Int, offset: Int, characteristic: BluetoothGattCharacteristic?) {
            super.onCharacteristicReadRequest(device, requestId, offset, characteristic)
            Logger.e(String.format("onCharacteristicReadRequest:%s,%s,%s,%s,%s", device?.name, device?.address, requestId, offset, characteristic!!.uuid))
            val response = "CHAR_" + (Math.random() * 100).toInt() //模拟数据
            // 响应客户端
            mBluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, response.toByteArray())
            logTV("客户端读取Characteristic[${characteristic.uuid}]:$response.trimIndent()")
        }

        @SuppressLint("MissingPermission")
        override fun onCharacteristicWriteRequest(device: BluetoothDevice?, requestId: Int, characteristic: BluetoothGattCharacteristic?, preparedWrite: Boolean, responseNeeded: Boolean, offset: Int, value: ByteArray?) {
            super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value)
            // 获取客户端发过来的数据
            val requestStr: String = String(value!!)
            Logger.e(String.format("onCharacteristicWriteRequest:%s,%s,%s,%s,%s,%s,%s,%s", device?.name, device?.address, requestId, characteristic!!.uuid, preparedWrite, responseNeeded, offset, requestStr))
            // 响应客户端
            mBluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value)
            logTV( "客户端写入Characteristic[${characteristic.uuid}]:\n"+ requestStr.trimIndent())
        }

        @SuppressLint("MissingPermission")
        override fun onDescriptorReadRequest(device: BluetoothDevice?, requestId: Int, offset: Int, descriptor: BluetoothGattDescriptor?) {
            super.onDescriptorReadRequest(device, requestId, offset, descriptor)
            Logger.e( String.format("onDescriptorReadRequest:%s,%s,%s,%s,%s", device?.name, device?.address, requestId, offset, descriptor?.uuid));
            var response = "DESC_" + (Math.random() * 100).toInt(); //模拟数据
            mBluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, response.toByteArray()); // 响应客户端
            logTV("客户端读取Descriptor[" + descriptor?.uuid + "]:\n" + response);
        }

        @SuppressLint("MissingPermission")
        override fun onDescriptorWriteRequest(device: BluetoothDevice?, requestId: Int, descriptor: BluetoothGattDescriptor?, preparedWrite: Boolean, responseNeeded: Boolean, offset: Int, value: ByteArray?) {
            super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value)
            // 获取客户端发过来的数据
            val valueStr: String = Arrays.toString(value)
            Logger.e(String.format("onDescriptorWriteRequest:%s,%s,%s,%s,%s,%s,%s,%s", device?.name, device?.address, requestId, descriptor!!.uuid, preparedWrite, responseNeeded, offset, valueStr))
            // 响应客户端
            mBluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value)
            logTV("客户端写入Descriptor[${descriptor.uuid}]\n:$valueStr")

            // 简单模拟通知客户端Characteristic变化
            if (Arrays.toString(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE).equals(valueStr)) {
                //是否开启通知
                val characteristic = descriptor.characteristic
               ThreadUtils.executeSubThread{
                    for (i in 0..4) {
                        SystemClock.sleep(3000)
                        val response = "CHAR_" + (Math.random() * 100).toInt() //模拟数据
                        characteristic.setValue(response)
                        mBluetoothGattServer.notifyCharacteristicChanged(device, characteristic, false)
                       logTV("通知客户端改变Characteristic[${characteristic.uuid}]:\n" + " $response")
                    }
                }
            }
        }

        @SuppressLint("MissingPermission")
        override fun onExecuteWrite(device: BluetoothDevice?, requestId: Int, execute: Boolean) {
            super.onExecuteWrite(device, requestId, execute)
            Logger.e(String.format("onExecuteWrite:%s,%s,%s,%s", device?.name, device?.address, requestId, execute));
        }

        @SuppressLint("MissingPermission")
        override fun onNotificationSent(device: BluetoothDevice?, status: Int) {
            super.onNotificationSent(device, status)
            Logger.e(String.format("onNotificationSent:%s,%s,%s", device?.name, device?.address, status));
        }

        @SuppressLint("MissingPermission")
        override fun onMtuChanged(device: BluetoothDevice?, mtu: Int) {
            super.onMtuChanged(device, mtu)
            Logger.e(String.format("onMtuChanged:%s,%s,%s", device?.name, device?.address, mtu));
        }
    }

    //BLE启动广播的监听
    private var mAdvertiseCallback: AdvertiseCallback = object : AdvertiseCallback() {
        override fun onStartSuccess(settingsInEffect: AdvertiseSettings?) {
            super.onStartSuccess(settingsInEffect)
            logTV("BLE广播开启成功")
        }

        override fun onStartFailure(errorCode: Int) {
            super.onStartFailure(errorCode)
            logTV("BLE广播开启失败,错误码是:$errorCode")
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_low_power_server)
        mTips = findViewById<TextView>(R.id.tips)
        var manager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
        var mBLE = manager.adapter

        //========启动BLE蓝牙广播===================================
        //广播设置(必须设置)
        var settings: AdvertiseSettings = AdvertiseSettings.Builder()
            //广播模式:低功耗,平衡,低延迟
            .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
            //发射功率级别:极低,低,中,高
            .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
            .setConnectable(true) //能否连接,广播分为连续关闭和不可连续广播
            .build()

        //广播数据(必须,广播启动就会发送)
        var advertiseData: AdvertiseData =
            AdvertiseData.Builder().setIncludeDeviceName(true) //包含蓝牙名称
                .setIncludeTxPowerLevel(true)//包含发射功率级别
                .addManufacturerData(1, byteArrayOf(23, 33))//设备厂商数据
                .build()

        //扫描响应数据(可选,当客户端扫描时才发送)
        var scanRespons: AdvertiseData =
            AdvertiseData.Builder().addManufacturerData(2, byteArrayOf(66, 66))//设备厂商数据,自定义
                .addServiceUuid(ParcelUuid(Contect.UUID_SERVICE))//服务的UUID
                //.addServiceData(ParcelUuid(Contect.UUID_SERVICE), byteArrayOf(2)) //服务数据,自定义
                .build()

        mBluetoothLeAdvertiser = mBLE.bluetoothLeAdvertiser
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            if (ActivityCompat.checkSelfPermission(
                    this, Manifest.permission.BLUETOOTH_ADVERTISE
                ) != PackageManager.PERMISSION_GRANTED
            ) {
                return
            }
        }
        mBluetoothLeAdvertiser.startAdvertising(
            settings, advertiseData, scanRespons, mAdvertiseCallback
        )


        //注意:必须要先开启可连接的BLE广播,其他设备才能发现并连接BLE服务端!
        //===========启动BLE蓝牙服务端===========================
        var service =
            BluetoothGattService(Contect.UUID_SERVICE, BluetoothGattService.SERVICE_TYPE_PRIMARY)

        //添加可读+通知characteristic
        var characteristicRead = BluetoothGattCharacteristic(
            Contect.UUID_CHAR_READ_NOTIFY,
            BluetoothGattCharacteristic.PROPERTY_READ or BluetoothGattCharacteristic.PROPERTY_NOTIFY,
            BluetoothGattCharacteristic.PERMISSION_READ
        )
        //添加可写
        characteristicRead.addDescriptor(
            BluetoothGattDescriptor(
                Contect.UUID_DESC_NOTITY, BluetoothGattCharacteristic.PERMISSION_WRITE
            )
        )
        //设置服务的属性
        service.addCharacteristic(characteristicRead)

        //添加可写charateristic
        var characteristicWrite = BluetoothGattCharacteristic(
            Contect.UUID_CHAR_WRITE,
            BluetoothGattCharacteristic.PROPERTY_WRITE,
            BluetoothGattCharacteristic.PERMISSION_WRITE
        );

        //设置服务的属性
        service.addCharacteristic(characteristicWrite)
        if (manager != null)
            mBluetoothGattServer = manager.openGattServer(this,mBluetoothGattServerCallback)
            mBluetoothGattServer.addService(service)

    }

    override fun onDestroy() {
        super.onDestroy()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            if (ActivityCompat.checkSelfPermission(
                    this, Manifest.permission.BLUETOOTH_ADVERTISE
                ) != PackageManager.PERMISSION_GRANTED
            ) {
                return
            }
        }
        mBluetoothLeAdvertiser?.stopAdvertising(mAdvertiseCallback)
        mBluetoothGattServer?.close()
    }

    private fun logTV(msg: String) {
        if (isDestroyed) return
        ThreadUtils.executeMainThread {
            ToastUtils.show(msg)
            mTips.append(msg + "\n\n")
        }
    }
}